let linePositions = []
let pickOverlayList = []
/**
 * @type {DE.Polyline|undefined}
 */
let line
let lineRules
let click, moving, db_click, cb

/**
 * @typedef LineOption
 * @type {Object}
 * @property {DE.Overlay} overlay - the overlay of click
 * @property {DE.VectorLayer} layer - the layer to add line
 * @property {string} type - the line type
 * @property {Object} style - the line style
 * @property {Object} attr - the line attr
 * @property {Function} callback - the callback fun
 * @property {PolylineRules} rules - the polylineRules
 */

/**
 * @typedef PolylineRules
 * @type {Object}
 * @property {Function} couldCreateLine 是否能够创建线判断，传入 overlay
 * @property {Function} clickRuleCheck 每次点击事件判断，传入 overlay
 * @property {Function} firstClickRuleCheck 第一次点击事件判断，传入 overlay
 * @property {Function} secondClickRuleCheck 第二次点击事件判断,传入 overlay
 */

const initProperty = () => {
  line = undefined
  linePositions = []
  pickOverlayList = []
  lineRules = undefined
  cb = () => {
    return null
  }
}

/**
 *
 * @param {LineOption} options
 */
export function drawLine (options = {}) {
  const {
    overlay,
    type,
    layer,
    rules,
    callback
  } = options
  cb = callback
  if (!type || !layer || !(layer instanceof DE.VectorLayer)) {
    return
  }
  // if (line) {
  //   layer.removeOverlay(line)
  // }

  unbindEvent()
  initProperty()
  lineRules = rules
  if (couldCreateLine(overlay)) {
    // 关掉自动隐藏（规则是鼠标没有悬浮在overlay上，则自动隐藏tooltip，让鼠标提示可以显示）
    const line = createLine(options)
    line.attr.equipIds = []
    overlay && line.attr.equipIds.push(overlay.overlayId)
    line.contextMenu = Events[type].contextMenu
    bindEvent(options)
    window.$tooltipAutoHide = false
  }
}

/**
 * create Polyline
 * @param {LineOption} options
 * @return {DE.Polyline}
 */
const createLine = (options = {}) => {
  const {
    overlay,
    layer,
    style,
    attr
  } = options
  line = new DE.Polyline([])
  // 下面定义线的业务属性
  line.attr = { ...line.attr, ...attr }
  // 设计线的样式
  style && line.setStyle(style)
  // 方式全局点击编辑事件触发到线
  line._hasEdit = false
  // 添加线到场景
  layer.addOverlay(line)
  // 原生方法修改线的位置树型
  const Cesium = DE.__namespace.Cesium
  line.delegate.polyline.positions = new Cesium.CallbackProperty((t) => {
    return linePositions
  }, false)
  return line
}

const unbindEvent = () => {
  pickOverlayList.forEach((overlay) => {
    overlay._hasEdit = true
  })
  pickOverlayList = []
  window?.$dmap?.off(DE.MouseEventType.CLICK, click)
  window?.$dmap?.off(DE.MouseEventType.MOUSE_MOVE, moving)
  window?.$dmap?.off(DE.MouseEventType.DB_CLICK, db_click)
  window.$tooltipAutoHide = true
  click = undefined
  moving = undefined
  db_click = undefined
}

const bindEvent = (options) => {
  const {
    overlay,
    type
  } = options

  click = Events[type].click
  moving = Events[type].moving
  db_click = Events[type].db_click
  overlay && overlay.position && linePositions.push(DE.Transform.transformWGS84ToCartesian(overlay.position))
  window?.$dmap?.on(DE.MouseEventType.CLICK, click)
  window?.$dmap?.on(DE.MouseEventType.MOUSE_MOVE, moving)
  window?.$dmap?.on(DE.MouseEventType.DB_CLICK, db_click)
}

/**
 * 是否能够创建线函数
 * @param {PolylineRules} rules
 * @param {DE.Overlay} overlay
 * @return {boolean} 是否能够创建线
 */
const couldCreateLine = (overlay) => {
  // 如果选择装备没有绑定过航迹线，可以给当前装备绑定航迹
  if (lineRules?.couldCreateLine && lineRules.couldCreateLine instanceof Function) {
    if (!overlay || !lineRules.couldCreateLine(overlay)) {
      return false
    }
  }
  return true
}

// 航线相关定义
const Events = {
  airline: {
    // 移动事件
    moving (e) {
      if (!e.surfacePosition || !e.windowPosition) {
        return
      }
      const tooltip = window?.$dmap?.tooltip
      if (tooltip) {
        tooltip.showAt(e.windowPosition, "左击拾取点位，双击完成绘制")
      }
      if (linePositions.length <= 1) {
        linePositions.push(e.surfacePosition)
      } else {
        linePositions.pop()
        linePositions.push(e.surfacePosition)
      }
    },
    // 左击事件
    click (e) {
      if (lineRules?.clickRuleCheck && lineRules.clickRuleCheck instanceof Function) {
        if (!lineRules.clickRuleCheck(e?.overlay, line, pickOverlayList)) {
          return
        }
      }
      e.surfacePosition && linePositions.push(e.surfacePosition)
    },
    // 双击事件，一般是绘制取消
    db_click: () => {
      // 自动隐藏tooltip设置为true
      if (line) {
        line.positions = DE.Transform.transformCartesianArrayToWGS84Array(linePositions)
        cb && cb(line)
      }
      unbindEvent()
    },
    // 线上绑定的右键菜单
    contextMenu: [
      {
        label: "删除",
        callback: (e) => {
          e?.overlay?.remove()
        },
        show: (e) => {
          return e.overlay?.attr?.type === "airline"
        },
        context: this
      }
    ]
  },
  // 直线相关定义，通信线，指挥线、打击线等都属于直线范畴，只是 type、style、连接条件不同
  straightLine: {
    // 移动事件
    moving (e) {
      const tooltip = window?.$dmap?.tooltip
      if (!e.surfacePosition || !e.windowPosition) {
        return
      }
      if (linePositions.length === 0) {
        tooltip.showAt(e.windowPosition, "左击拾取第一个装备，双击取消")
      } else if (linePositions.length === 1) {
        tooltip.showAt(e.windowPosition, "左击拾取第二个装备，双击取消")
        linePositions.push(e.surfacePosition)
      } else if (linePositions.length === 2) {
        tooltip.showAt(e.windowPosition, "左击拾取第二个装备，双击取消")
        linePositions.pop()
        linePositions.push(e.surfacePosition)
      }
    },
    // 左击事件
    click (e) {
      // category可以根据业务来定，这里基于 public/testData/equipList 的伪数据定义 category 为 1010 的为可挂载装备
      // 点击对象可根据业务属性修改
      // 如果直线只涉及两次认证，第一次校验规则 clickRuleCheck
      if (lineRules?.clickRuleCheck && lineRules.clickRuleCheck instanceof Function) {
        if (!lineRules.clickRuleCheck(e?.overlay, line, pickOverlayList)) {
          return
        }
      }
      e.overlay._hasEdit = false
      pickOverlayList.push(e.overlay)
      if (e.overlay.position && linePositions.length === 0) {
        if (lineRules?.firstClickRuleCheck && lineRules.firstClickRuleCheck instanceof Function) {
          if (!e.overlay || !lineRules.firstClickRuleCheck(e?.overlay)) {
            return
          }
        }
        linePositions.push(DE.Transform.transformWGS84ToCartesian(e.overlay.position))
        // 记录第一个点
        line.attr.startId = e.overlay.overlayId
        line.attr.equipIds.push(e.overlay.overlayId)
      }
      if (linePositions.length === 2) {
        // 第二次校验规则
        if (lineRules?.secondClickRuleCheck && lineRules.secondClickRuleCheck instanceof Function) {
          if (!lineRules.secondClickRuleCheck(e?.overlay, line, pickOverlayList)) {
            return
          }
        }
        linePositions.pop()
        linePositions.push(DE.Transform.transformWGS84ToCartesian(e.overlay.position))
        line.positions = linePositions
        // 记录第二个点, id为可修改属性，overlayId为不可修改属性
        line.attr.endId = e.overlay.overlayId
        line.attr.equipIds.push(e.overlay.overlayId)
        cb && cb(line)
        unbindEvent()
      }
    },
    // 双击事件，一般是绘制取消
    db_click () {
      // 自动隐藏tooltip设置为true
      // 双击取消
      line.remove()
      unbindEvent()
    },
    // 线上绑定的右键菜单
    contextMenu: [
      {
        label: "删除",
        callback: (e) => {
          pickOverlayList && pickOverlayList.forEach((overlay) => {
            overlay._hasEdit = true
          })
          pickOverlayList = []
          e?.overlay?.remove()
        },
        show: (e) => {
          return true
        },
        context: this
      }
    ]
  }
}

/**
 * get specific line of overlay
 * @param {DE.Overlay} overlay
 * @param {Function|undefined} filter
 * @return {*[]} polyline
 */
export function getLinesOfOverlayWithFilter (overlay, filter) {
  const res = []
  const lines = window?.$actionPlotLayer?.getOverlays()
  if (!overlay || !filter || !lines) {
    return res
  }

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i]
    // 线上挂载的装备是否为 相同的overlayId 且 attr 相同
    if (filter(overlay, line)) {
      res.push(line)
    }
  }
  return res
}

/**
 * overlay的位置修改时同步修改相关 lines 的位置
 * @param {DE.Overlay} overlay
 * @return {boolean}
 */
export function changeLinesPositionBasedBindOverlay (overlay) {
  if (!overlay && !overlay.position) {
    return false
  }
  const lines = getLinesOfOverlayWithFilter(overlay, (overlay, line) => {
    if (overlay && line) {
      return line?.attr?.equipIds?.includes(overlay.overlayId)
    } else {
      return false
    }
  })
  lines.forEach((line) => changeLinePositions(line, overlay))
  return true
}

/**
 * 图元删除同步删除关联线
 * @param {DE.Billboard} overlay
 */
export function removeLinesOfOverlay (overlay) {
  if (!overlay) {
    return
  }
  const lines = getLinesOfOverlayWithFilter(overlay, (overlay, line) => {
    if (overlay && line) {
      return line.attr?.equipIds?.includes(overlay.overlayId)
    } else {
      return false
    }
  })
  lines.forEach((line) => line?.remove())
}

const changeLinePositions = (line, overlay) => {
  const {
    position,
    overlayId
  } = overlay
  if (line && position) {
    const temp = []
    if (line.attr?.endId === overlayId) {
      // 如果移动的末位点的装备
      for (let i = 0; i < line.positions.length - 1; i++) {
        temp.push(line.positions[i])
      }
      line.positions = [...temp, position]
    } else {
      // 如果移动的首位点的装备
      for (let i = 1; i < line.positions.length; i++) {
        temp.push(line.positions[i])
      }
      line.positions = [position, ...temp]
    }
  }
}


